package com.path.planning.util;

import com.path.planning.entity.RoutingNetwork;
import lombok.extern.slf4j.Slf4j;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.io.WKTReader;
import org.locationtech.jts.io.WKTWriter;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * 路网数据预处理器
 * 根据几何数据自动生成其他字段
 */
@Component
@Slf4j
public class NetworkDataProcessor {

    private final WKTReader wktReader = new WKTReader();
    private final WKTWriter wktWriter = new WKTWriter();
    private final GeometryFactory geometryFactory = new GeometryFactory();

    /**
     * 处理路网数据
     */
    public List<RoutingNetwork> processNetworkData(List<Map<String, Object>> rawData) {
        log.info("开始处理路网数据 - 原始数据量: {}", rawData.size());
        
        List<RoutingNetwork> processedData = new ArrayList<>();
        Map<String, Long> nodeIdMap = new HashMap<>(); // 坐标到节点ID的映射
        long nodeIdCounter = 1;

        for (Map<String, Object> rawItem : rawData) {
            try {
                RoutingNetwork network = new RoutingNetwork();

                // 设置名称
                if (rawItem.containsKey("name") && rawItem.get("name") != null) {
                    network.setName(rawItem.get("name").toString());
                }

                // 解析几何数据
                String geometryWkt = rawItem.get("geom").toString();
                Geometry geometry = wktReader.read(geometryWkt);
                network.setGeom(geometry);

                // 计算长度
                if (rawItem.containsKey("length") && rawItem.get("length") != null) {
                    try {
                        network.setLength(Double.valueOf(rawItem.get("length").toString()));
                    } catch (NumberFormatException e) {
                        // 如果长度格式错误，自动计算
                        network.setLength(calculateGeometryLength(geometry));
                    }
                } else {
                    // 自动计算长度
                    network.setLength(calculateGeometryLength(geometry));
                }

                // 生成起点和终点节点ID
                Long[] sourceTarget = generateSourceTargetIds(geometry, nodeIdMap, nodeIdCounter);
                network.setSource(sourceTarget[0]);
                network.setTarget(sourceTarget[1]);
                nodeIdCounter = Math.max(nodeIdCounter, Math.max(sourceTarget[0], sourceTarget[1])) + 1;

                // 生成起点和终点坐标
                generateSourceTargetPoints(network, geometry);

                processedData.add(network);

            } catch (Exception e) {
                log.error("处理路网数据失败: {}", rawItem, e);
            }
        }

        log.info("路网数据处理完成 - 处理后数据量: {}", processedData.size());
        return processedData;
    }

    /**
     * 计算几何长度
     */
    private double calculateGeometryLength(Geometry geometry) {
        if (geometry instanceof LineString) {
            LineString lineString = (LineString) geometry;
            return calculateSphericalLength(lineString);
        }
        return 0.0;
    }

    /**
     * 计算球面长度
     */
    private double calculateSphericalLength(LineString lineString) {
        double totalLength = 0.0;
        Coordinate[] coordinates = lineString.getCoordinates();
        
        for (int i = 0; i < coordinates.length - 1; i++) {
            double lat1 = Math.toRadians(coordinates[i].y);
            double lon1 = Math.toRadians(coordinates[i].x);
            double lat2 = Math.toRadians(coordinates[i + 1].y);
            double lon2 = Math.toRadians(coordinates[i + 1].x);
            
            // Haversine公式计算球面距离
            double dlat = lat2 - lat1;
            double dlon = lon2 - lon1;
            double a = Math.sin(dlat / 2) * Math.sin(dlat / 2) +
                      Math.cos(lat1) * Math.cos(lat2) *
                      Math.sin(dlon / 2) * Math.sin(dlon / 2);
            double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
            double distance = 6371000 * c; // 地球半径6371km
            
            totalLength += distance;
        }
        
        return totalLength;
    }

    /**
     * 生成起点和终点节点ID
     */
    private Long[] generateSourceTargetIds(Geometry geometry, Map<String, Long> nodeIdMap, long startId) {
        if (!(geometry instanceof LineString)) {
            return new Long[]{null, null};
        }

        LineString lineString = (LineString) geometry;
        Coordinate[] coordinates = lineString.getCoordinates();
        
        if (coordinates.length < 2) {
            return new Long[]{null, null};
        }

        Coordinate startCoord = coordinates[0];
        Coordinate endCoord = coordinates[coordinates.length - 1];

        // 生成起点ID
        String startKey = startCoord.x + "," + startCoord.y;
        Long sourceId = nodeIdMap.get(startKey);
        if (sourceId == null) {
            sourceId = startId++;
            nodeIdMap.put(startKey, sourceId);
        }

        // 生成终点ID
        String endKey = endCoord.x + "," + endCoord.y;
        Long targetId = nodeIdMap.get(endKey);
        if (targetId == null) {
            targetId = startId++;
            nodeIdMap.put(endKey, targetId);
        }

        return new Long[]{sourceId, targetId};
    }

    /**
     * 生成起点和终点坐标
     */
    private void generateSourceTargetPoints(RoutingNetwork network, Geometry geometry) {
        if (!(geometry instanceof LineString)) {
            return;
        }

        LineString lineString = (LineString) geometry;
        Coordinate[] coordinates = lineString.getCoordinates();
        
        if (coordinates.length < 2) {
            return;
        }

        // 设置起点坐标
        Coordinate startCoord = coordinates[0];
        Point sourcePoint = geometryFactory.createPoint(startCoord);
        network.setSourcePoint(sourcePoint);

        // 设置终点坐标
        Coordinate endCoord = coordinates[coordinates.length - 1];
        Point targetPoint = geometryFactory.createPoint(endCoord);
        network.setTargetPoint(targetPoint);
    }
}
